/* proc_hello.c */
#include <linux/module.h> /* Specifically, a module */
#include <linux/kernel.h> /* We're doing kernel work */
#include <linux/proc_fs.h> /* Necessary because we use the proc fs */
#define procfs_name "helloworld"

struct proc_dir_entry *Our_Proc_File;
int procfile_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *eof, void *data)
{
  int ret;
  printk(KERN_INFO "procfile_read (/proc/%s) called\n", procfs_name);
  /*
   * We give all of our information in one go, so if the user asks us if we 
   * have more information the answer should always be no.
   *
   * This is important because the standard read function from the library 
   * would continue to issue the read system call until the kernel replies
   * that it has no more information, or until its buffer is filled.
   */
  if (offset > 0) {
	printk(KERN_INFO "offset > 0\n");
	/* we have finished to read, return 0 */
	ret = 0;
  } else {
	/* fill the buffer, return the buffer size */
	printk(KERN_INFO "offset <= 0\n");
	ret = sprintf(buffer, "HelloWorld!\n");
  }
  return ret;
}
int init_module()
{
  Our_Proc_File = create_proc_entry(procfs_name, 0644, NULL);
  if (Our_Proc_File == NULL) {
	remove_proc_entry(procfs_name, &proc_root);
	printk(KERN_ALERT "Error: Could not initialize /proc/%s\n", procfs_name);
	return -ENOMEM;
  }
  Our_Proc_File->read_proc = procfile_read;
  Our_Proc_File->owner = THIS_MODULE;
  Our_Proc_File->mode = S_IFREG | S_IRUGO;
  Our_Proc_File->uid = 0;
  Our_Proc_File->gid = 0;
  Our_Proc_File->size = 37;
  printk(KERN_INFO "/proc/%s created\n", procfs_name);
  return 0; /* everything is ok */
}
void cleanup_module()
{
  remove_proc_entry(procfs_name, &proc_root);
  printk(KERN_INFO "/proc/%s removed\n", procfs_name);
}

